"""
更新archive集
"""
import numpy as np


def getNonDominationPops(pops, fits):
    """快速得到非支配解集 
    Params:
        pops: 种群，nPop * nChr 数组
        fits: 适应度， nPop * nF 数组 
    Return: 
        ranks: 每个个体所对应的等级，一维数组 
    """
    nPop = pops.shape[0]
    nF = fits.shape[1]  # 目标函数的个数 
    ranks = np.ones(nPop, dtype=np.int32)
    nPs = np.zeros(nPop)  # 每个个体p被支配解的个数 
    for i in range(nPop):
        for j in range(nPop):
            if i == j:
                continue
            isDom1 = fits[i] <= fits[j]
            isDom2 = fits[i] < fits[j]
            # 是否被支配-> i被j支配 
            if sum(~isDom2) == nF and sum(~isDom1) >= 1:
                nPs[i] += 1
    r = 0  # 当前等级为 0， 等级越低越好 
    indices = np.arange(nPop)
    rIdices = indices[nPs == 0]  # 当前被支配数为0的索引
    ranks[rIdices] = 0  # 将支配解=0（受其他解支配=0）的层级置为0
    return pops[ranks == 0], fits[ranks == 0]  # 选出第一层级的种群及其对应的适应度


def updateArchive(pops, fits, archive, arFits):
    """根据当前新的种群更新archive
    Params:
        :param pops:当前粒子群（pBest的上一步种群）,但是该粒子群通过公式经过了移动
        :param fits:当前粒子群的适应度（pFits的上一步适应度），该粒子群通过公式经过了移动
        :param archive: pops[ranks == 0]，相对于上面的pops,比他们早出生一代计算出来的
        :param arFits: fits[ranks == 0]
        :return: newArchive、newArFit
    """
    # 获取当前种群的非支配解
    nonDomPops, nonDomFits = getNonDominationPops(pops, fits)
    isCh = np.zeros(nonDomPops.shape[0]) >= 1  # 开始全部设置为false
    nF = fits.shape[1]  # 目标个数 
    for i in range(nonDomPops.shape[0]):
        # 判断arFits中是否有解支配当前种群的非支配解
        isDom1 = nonDomFits[i] >= arFits
        isDom2 = nonDomFits[i] > arFits
        isDom = (np.sum(isDom1, axis=1) == nF) & (np.sum(isDom2, axis=1) >= 1)
        if np.sum(~isDom) >= 1:  #
            # isDom=[False False False  True False False  True]这种情况时也会被添加进去
            # 说明（原始粒子群）archive集中没有一个解可以支配该解，那么将其添加进去
            isCh[i] = True  # 设置为可供选择 
    # 如果有支配解产生，将其添加到archive种
    if np.sum(isCh) >= 1:
        archive = np.concatenate((archive, nonDomPops[isCh]), axis=0)
        arFits = np.concatenate((arFits, nonDomFits[isCh]), axis=0)
    return archive, arFits


if __name__ == "__main__":
    pops = np.array([[-0.96856579, 1.51885237, -0.47154205], [0.60635926, -1.01725988, 1.82093581]])
    fits = np.array([[2, 3], [1, 1]])
    archive, arFits = getNonDominationPops(pops, fits)
    print("archive", archive)
    print("arFits", arFits)

    # [False False False False False]
    print((np.zeros(5) >= 1))

    isDom = np.array([False, False, False, True, False, False, True])
    # 5
    print((np.sum(~isDom)))
    # True
    print((np.sum(~isDom) >= 1))
